package com.jstyle.jclife.fragment;

import android.content.Context;
import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.ColorDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.support.constraint.ConstraintLayout;
import android.support.v4.app.Fragment;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;

import com.google.android.flexbox.FlexboxLayoutManager;
import com.jstyle.jclife.R;
import com.jstyle.jclife.activity.HealthHistoryActivity;
import com.jstyle.jclife.adapter.HistoryShowAdapter;
import com.jstyle.jclife.adapter.HrvYearDataAdapter;
import com.jstyle.jclife.daoManager.HealthDataDaoManager;
import com.jstyle.jclife.model.HealthData;
import com.jstyle.jclife.model.HealthShowData;
import com.jstyle.jclife.utils.ChartDataUtil;
import com.jstyle.jclife.utils.DateUtil;
import com.jstyle.jclife.utils.ResolveData;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import butterknife.BindArray;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import lecho.lib.hellocharts.model.ArcValue;
import lecho.lib.hellocharts.model.BpValue;
import lecho.lib.hellocharts.model.PieChartData;
import lecho.lib.hellocharts.view.LineChartView;
import lecho.lib.hellocharts.view.PieChartView;

/**
 * A simple {@link Fragment} subclass.
 * Activities that contain this fragment must implement the
 * {@link OnFragmentInteractionListener} interface
 * to handle interaction events.
 * Use the {@link HealthHistoryYearFragment#newInstance} factory method to
 * create an instance of this fragment.
 */
public class HealthHistoryYearFragment extends BaseFragment {
    // TODO: Rename parameter arguments, choose names that match
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";

    @BindView(R.id.RecyclerView_history_detail)
    RecyclerView RecyclerViewHistoryDetail;
    @BindView(R.id.bt_history_dataType)
    Button btHistoryDataType;
    @BindView(R.id.RecyclerView_history)
    RecyclerView RecyclerViewHistory;
    Unbinder unbinder;
    @BindView(R.id.PieChartView_history)
    PieChartView PieChartViewHistory;
    @BindView(R.id.tv_count_normal)
    TextView tvCountNormal;
    @BindView(R.id.tv_bp_normal)
    TextView tvBpNormal;
    @BindView(R.id.tv_count_low)
    TextView tvCountLow;
    @BindView(R.id.tv_bp_low)
    TextView tvBpLow;
    @BindView(R.id.tv_count_high)
    TextView tvCountHigh;
    @BindView(R.id.tv_bp_high)
    TextView tvBpHigh;
    @BindView(R.id.tv_count_error)
    TextView tvCountError;
    @BindView(R.id.tv_bp_error)
    TextView tvBpError;
    @BindView(R.id.ConstraintLayout_bp)
    ConstraintLayout ConstraintLayoutBp;
    @BindView(R.id.lineChartView_health_year)
    LineChartView lineChartViewHealthYear;
    private ArrayList<String> listContent;
    private HistoryShowAdapter historyShowAdapter;
    // TODO: Rename and change types of parameters
    private int mParam1;
    private String mParam2;
    private static final String TAG = "HealthHistoryYearFragme";
    private OnFragmentInteractionListener mListener;
    private HashMap<Integer, List<Integer>> dateHashMap = new HashMap<>();
    private boolean isBusy;
    private String[] monthArray;
    private float[] yearData;
    private int maxHr;
    private int minHr;
    private int avgHr;
    @BindArray(R.array.bp_color_arrays)
    int[] bpColorArray;
    @BindArray(R.array.stress_color_arrays)
    int[] stressColorArray;
    @BindArray(R.array.color_hrv_array)
    int[] hrvColorArray;
    @BindArray(R.array.health_hrv)
    String[] arrayHrv;
    @BindArray(R.array.health_pressure)
    String[] arrayPressure;
    @BindArray(R.array.string_bp_array)
    String[] arrayBp;
    @BindArray(R.array.string_hrv_array)
    String[] arrayHrvString;
    @BindArray(R.array.string_pressure_array)
    String[] arrayStressString;
    @BindArray(R.array.health_blood)
    String[] arrayBlood;
    int[] statusArray;
    int[] dataColorArray;
    String[] dataTextArray;
    HashMap<Integer, List<BpValue>> dateBpHashMap = new HashMap<>();
    private HealthData lastHealthData;
    private Typeface mFace;

    public HealthHistoryYearFragment() {
        // Required empty public constructor
    }

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @param param1 Parameter 1.
     * @return A new instance of fragment HealthHistoryYearFragment.
     */
    // TODO: Rename and change types and number of parameters
    public static HealthHistoryYearFragment newInstance(int param1) {
        HealthHistoryYearFragment fragment = new HealthHistoryYearFragment();
        Bundle args = new Bundle();
        args.putInt(ARG_PARAM1, param1);

        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getInt(ARG_PARAM1);

        }
    }

    private void setListContent() {
        listContent = new ArrayList<>();
        String[] arrayContent = null;
        switch (mParam1) {
            case HealthHistoryActivity.DATA_BLOOD:
                arrayContent = arrayBlood;
                break;
            case HealthHistoryActivity.DATA_HRV:
                arrayContent = arrayHrv;
                break;
            case HealthHistoryActivity.DATA_PRESSURE:
                arrayContent = arrayPressure;
                break;
        }
        listContent.addAll(Arrays.asList(arrayContent));

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_health_history_year, container, false);
        unbinder = ButterKnife.bind(this, view);
        init();
        return view;
    }

    private void init() {
        mFace = Typeface.createFromAsset(getActivity().getAssets(), "Brandon_reg.otf");

        FlexboxLayoutManager layoutManager2 = new FlexboxLayoutManager(getActivity());
        setListContent();
        historyShowAdapter = new HistoryShowAdapter(listContent);
        RecyclerViewHistoryDetail.setAdapter(historyShowAdapter);
        RecyclerViewHistoryDetail.setLayoutManager(layoutManager2);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity()) {
            @Override
            public boolean canScrollVertically() {
                return false;
            }
        };
        linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        RecyclerViewHistory.setLayoutManager(linearLayoutManager);
        DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL);
        ColorDrawable colorDrawable = new ColorDrawable();
        colorDrawable.setColor(Color.DKGRAY);
        dividerItemDecoration.setDrawable(colorDrawable);
        RecyclerViewHistory.addItemDecoration(dividerItemDecoration);
        initText();
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        updateDate(String.valueOf(year), mParam1);
    }

    private void initText() {
        switch (mParam1) {
            case HealthHistoryActivity.DATA_BLOOD:
                dataColorArray = bpColorArray;
                dataTextArray = arrayBp;
                break;
            case HealthHistoryActivity.DATA_HRV:
                dataColorArray = hrvColorArray;
                dataTextArray = arrayHrvString;
                break;
            case HealthHistoryActivity.DATA_PRESSURE:
                dataColorArray = stressColorArray;
                dataTextArray = arrayStressString;
                break;
        }
    }

    String year = "";

    @Override
    public void updateDate(String date, final int dataType) {
        year = date;
        final String startDate = date.substring(2) + ".01.01";
        final String endDate = date.substring(2) + ".12.31";
        dateHashMap.clear();
        dateBpHashMap.clear();
        yearHashMap.clear();
        ConstraintLayoutBp.setVisibility(dataType== HealthHistoryActivity.DATA_BLOOD?View.VISIBLE:View.GONE);
        lineChartViewHealthYear.setVisibility(dataType== HealthHistoryActivity.DATA_BLOOD?View.GONE:View.VISIBLE);

        Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> e) throws Exception {
                healthDataList = HealthDataDaoManager.queryDayData(startDate + " 00:00:00", endDate + " 23:59:59");
                lastHealthData = healthDataList.size() == 0 ? new HealthData() : healthDataList.get(0);

                initHealthData(healthDataList, dataType);

                e.onComplete();
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<Integer>() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(Integer value) {
                Log.i(TAG, "onNext: " + value);
            }

            @Override
            public void onError(Throwable e) {
                disMissLoadingDialog();
                isBusy = false;
                Log.i(TAG, "onError: " + e.getMessage());
            }

            @Override
            public void onComplete() {
                disMissLoadingDialog();
                if (mParam1 == HealthHistoryActivity.DATA_BLOOD) {
                    setWeekBpChartViewData();
                } else {
                    setWeekChartViewData();
                    initRecyclerViewHistory();
                }

                isBusy = false;
            }
        });

    }

    private void initRecyclerBpViewHistory() {
        List<HealthData> healthDataList = new ArrayList<>();
        for (Map.Entry<Integer, BpValue> entry : yearHashMap.entrySet()) {
            BpValue bpValue = entry.getValue();
            int month = entry.getKey();
            HealthData healthData = new HealthData();
            healthData.setHighBloodPressure(bpValue.getHighValue());
            healthData.setLowBloodPressure(bpValue.getLowValue());
            healthData.setTime(year + "." + String.valueOf(month + 1));
            healthDataList.add(healthData);
        }
        Collections.sort(healthDataList, new Comparator<HealthData>() {
            @Override
            public int compare(HealthData o1, HealthData o2) {
                Date date = DateUtil.String2Date(o1.getTime(), DateUtil.DATA_Year_FormatString);
                Date date2 = DateUtil.String2Date(o2.getTime(), DateUtil.DATA_Year_FormatString);
                return date.before(date2) ? 1 : -1;
            }
        });
//        HrvYearDataAdapter hrvDataAdapter = new HrvYearDataAdapter(healthDataList, HealthHistoryActivity.DATA_BLOOD);
//        RecyclerViewHistory.setAdapter(hrvDataAdapter);
        List<String> listHeart = new ArrayList<>();//总计列表
        listHeart.add(healthDataList.size() + "");
        String highDay = maxHealthData == null ? "--/--" : maxHealthData.getHighBloodPressure() + "/" + maxHealthData.getLowBloodPressure();
        String lowDay = minHealthData == null ? "--/--" : minHealthData.getHighBloodPressure() + "/" + minHealthData.getLowBloodPressure();
        listHeart.add(highDay);
        listHeart.add(lowDay);
        historyShowAdapter.setStepData(listHeart);
    }

    private void setWeekChartViewData() {
        float max=0;
        for(Float value:yearData){
            max=Math.max(value,max);
        }
        float top = (max / 10 + 1) * 10;
        ChartDataUtil.initDataChartView(lineChartViewHealthYear, -0.5f, top + 5,12, 0);
        lineChartViewHealthYear.setLineChartData(ChartDataUtil.getHealthYearLineChart(yearData, top));

        List<String> listHeart = new ArrayList<>();//总计列表
        listHeart.add(avgHr + "");
        listHeart.add(maxHr + "");
        listHeart.add((minHr == 300 ? 0 : minHr) + "");
        historyShowAdapter.setStepData(listHeart);
    }

    private void setWeekBpChartViewData() {
        List<ArcValue> arcValues = new ArrayList<>();
        for (int i = 0; i < statusArray.length; i++) {
            int count = statusArray[i];
            if (count != 0)
                arcValues.add(new ArcValue(count, dataColorArray[i]));
        }
        tvBpNormal.setText(dataTextArray[0]);
        tvBpLow.setText(dataTextArray[1]);
        tvBpHigh.setText(dataTextArray[2]);
        tvBpError.setText(dataTextArray[3]);
        tvBpNormal.setTextColor(dataColorArray[0]);
        tvBpLow.setTextColor(dataColorArray[1]);
        tvBpHigh.setTextColor(dataColorArray[2]);
        tvBpError.setTextColor(dataColorArray[3]);
        tvCountNormal.setText(String.valueOf(statusArray[0]) + getString(R.string.Times));
        tvCountLow.setText(String.valueOf(statusArray[1]) + getString(R.string.Times));
        tvCountHigh.setText(String.valueOf(statusArray[2]) + getString(R.string.Times));
        tvCountError.setText(String.valueOf(statusArray[3]) + getString(R.string.Times));
        initPieChartData(arcValues);

    }

    private void initPieChartData(List<ArcValue> arcValues) {
        PieChartData pieChartData = new PieChartData(arcValues);
        pieChartData.setHasLabelsOnlyForSelected(arcValues.size() != 0);
        if (arcValues.size() == 0) {
            arcValues.add(new ArcValue(1, getResources().getColor(R.color.history_data_hint)).setArcSpacing(0));
            pieChartData.setCenterText1(getString(R.string.No_data));
        } else {
            String lastText = ResolveData.getLastDataString(lastHealthData, mParam1);
            int textColor = Color.WHITE;
            String label = "";
            if (mParam1 == HealthHistoryActivity.DATA_PRESSURE) {
                int level = ResolveData.getStressLevel(lastHealthData.getPressure());
                Log.i(TAG, "setWeekBpChartViewData: " + lastHealthData.getTime());
                textColor = dataColorArray[level];
                label = "\n" + dataTextArray[level];
            } else if (mParam1 == HealthHistoryActivity.DATA_HRV) {
                int level = ResolveData.getHrvLevel(lastHealthData.getHrv());
                textColor = dataColorArray[level];
                label = "\n" + dataTextArray[level];
            } else if (mParam1 == HealthHistoryActivity.DATA_BLOOD) {
                textColor = getResources().getColor(R.color.style_text_color);
            }
            pieChartData.setCenterText1(getString(R.string.The_last_time));
            pieChartData.setCenterText2Color(textColor);
            pieChartData.setCenterText2FontSize(12);
            pieChartData.setCenterText2(lastText + label);
        }
        pieChartData.setCenterText1Typeface(mFace);
        pieChartData.setCenterText2Typeface(mFace);
        pieChartData.setHasCenterCircle(true);
        pieChartData.setCenterText1Color(getResources().getColor(R.color.style_text_color));
        pieChartData.setCenterText1FontSize(12);
        pieChartData.setCenterCircleColor(getResources().getColor(R.color.main_bg_color));
        PieChartViewHistory.setChartRotationEnabled(false);
        PieChartViewHistory.setValueSelectionEnabled(true);
        PieChartViewHistory.setPieChartData(pieChartData);
        initRecyclerBpViewHistory();

    }

    List<HealthData> healthDataList;

    private void initRecyclerViewHistory() {
        List<HealthData> healthDataList = new ArrayList<>();
        for (int i = 0; i < 12; i++) {
            float value = yearData[i];
            if (value == 0) continue;
            HealthData healthData = new HealthData();
            healthData.setHrv((int) value);
            healthData.setTime(year + "." + String.valueOf(i + 1));
            healthDataList.add(healthData);
        }
        Collections.sort(healthDataList, new Comparator<HealthData>() {
            @Override
            public int compare(HealthData o1, HealthData o2) {
                Date date = DateUtil.String2Date(o1.getTime(), DateUtil.DATA_Year_FormatString);
                Date date2 = DateUtil.String2Date(o2.getTime(), DateUtil.DATA_Year_FormatString);
                return date.before(date2) ? 1 : -1;
            }
        });
        List<HealthShowData> healthShowDataList = new ArrayList<>();
        for (Map.Entry<Integer, List<Integer>> entry : dateHashMap.entrySet()) {
            List<Integer> list = entry.getValue();
            int month = entry.getKey();
            int dayMax = 0;
            int dayMin = 300;
            for (Integer value : list) {
                dayMax = Math.max(value, dayMax);
                dayMin = Math.min(value, dayMin);
            }
            String date=year+"."+month;
            HealthShowData healthShowData = new HealthShowData();
            healthShowData.setTime(DateUtil.getShowYearDate(getContext(),date));
            healthShowData.setContent(mParam1==HealthHistoryActivity.DATA_HRV?getString(R.string.hrv):getString(R.string.stress));
            healthShowData.setMaxValue(dayMax);
            healthShowData.setMinValue(dayMin);
            healthShowDataList.add(healthShowData);
        }

        HrvYearDataAdapter hrvYearDataAdapter=new HrvYearDataAdapter(healthShowDataList);
        RecyclerViewHistory.setAdapter(hrvYearDataAdapter);
    }

    HealthData maxHealthData = null;
    HealthData minHealthData = null;

    private void initHealthData(List<HealthData> healthDataList, int dataType) {
        maxHr = 0;
        minHr = 300;
        statusArray = new int[4];
        if (dataType == HealthHistoryActivity.DATA_BLOOD) {
            maxHealthData = null;
            minHealthData = null;

            int maxDayHr = 0;
            int minDayHr = 300;
            for (HealthData healthData : healthDataList) {
                String time = healthData.getTime();
                int month = Integer.parseInt(time.substring(3, 5));
                List<BpValue> list = dateBpHashMap.get(month);
                int highValue = healthData.getHighBloodPressure();
                int lowValue = healthData.getLowBloodPressure();
                if (highValue != 0 && lowValue != 0) {
                    if (list == null) {
                        list = new ArrayList<>();
                    }
                    ResolveData.getBPStatus(highValue, lowValue, statusArray);
                    list.add(new BpValue(highValue, lowValue));
                    dateBpHashMap.put(month, list);
                    if (highValue > maxDayHr) {
                        maxDayHr = highValue;
                        maxHealthData = healthData;
                    }
                    if (lowValue < minDayHr) {
                        minDayHr = lowValue;
                        minHealthData = healthData;
                    }
                }
            }
            getYearBpData();
        } else {
            for (HealthData healthData : healthDataList) {
                String time = healthData.getTime();
                int month = Integer.parseInt(time.substring(3, 5));
                List<Integer> list = dateHashMap.get(month);
                int value = ResolveData.getData(healthData, dataType);
                if (dataType == HealthHistoryActivity.DATA_HRV) {
                    statusArray[ResolveData.getHrvLevel(healthData.getHrv())]++;
                } else if (dataType == HealthHistoryActivity.DATA_PRESSURE) {
                    statusArray[ResolveData.getStressLevel(healthData.getPressure())]++;
                }
                if (value != 0) {
                    if (list == null) {
                        list = new ArrayList<>();
                    }
                    maxHr = Math.max(value, maxHr);
                    minHr = Math.min(value, minHr);
                    list.add(value);
                    dateHashMap.put(month, list);
                }
            }
            getYearData();
        }
    }

    private void getYearData() {
        yearData = new float[12];
        int totalYear = 0;
        int size = 0;
        for (Map.Entry<Integer, List<Integer>> entry : dateHashMap.entrySet()) {
            List<Integer> list = entry.getValue();
            int month = entry.getKey();
            float totalHR = 0;
            float count = 0;
            for (Integer value : list) {
                totalHR += value;
                count++;
                size++;
            }
            totalYear += totalHR;
            yearData[month - 1] = count == 0 ? 0 : (int) (totalHR / count);
        }
        avgHr = size == 0 ? 0 : totalYear / size;
    }

    HashMap<Integer, BpValue> yearHashMap = new HashMap<>();

    private void getYearBpData() {
        int totalYear = 0;
        int size = 0;
        for (Map.Entry<Integer, List<BpValue>> entry : dateBpHashMap.entrySet()) {
            List<BpValue> list = entry.getValue();
            int month = entry.getKey();
            float totalHigh = 0;
            float totalLow = 0;
            float count = 0;
            for (BpValue value : list) {
                totalHigh += value.getHighValue();
                totalLow += value.getLowValue();
                count++;
                size++;
            }
            // totalYear += totalHR;
            int monthHigh = count == 0 ? 0 : (int) (totalHigh / count);
            int monthLow = count == 0 ? 0 : (int) (totalLow / count);
            yearHashMap.put(month - 1, new BpValue(monthHigh, monthLow));
        }
        // avgHr = size == 0 ? 0 : totalYear / size;
    }

    // TODO: Rename method, update argument and hook method into UI event
    public void onButtonPressed(Uri uri) {
        if (mListener != null) {
            mListener.onFragmentInteraction(uri);
        }
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);

    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        unbinder.unbind();
    }

    /**
     * This interface must be implemented by activities that contain this
     * fragment to allow an interaction in this fragment to be communicated
     * to the activity and potentially other fragments contained in that
     * activity.
     * <p>
     * See the Android Training lesson <a href=
     * "http://developer.android.com/training/basics/fragments/communicating.html"
     * >Communicating with Other Fragments</a> for more information.
     */
    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        void onFragmentInteraction(Uri uri);
    }
}
